// Copyright (C) 1953-2021 NUDT
// Verilog module name - mapped_frame_outport
// Version: V3.2.2.20211102
// Created:
//         by - fenglin 
////////////////////////////////////////////////////////////////////////////
// Description:
//         descriptor extract
///////////////////////////////////////////////////////////////////////////

`timescale 1ns/1ps
 
module mapped_frame_outport
(
        i_clk  ,
        i_rst_n,
            
        i_add_tag_flag      ,    
        iv_ipv              ,
        iv_flowid           ,
        i_replication_flag  ,
        iv_seq_num          ,
        iv_inject_dbufid    ,
        i_lookup_finish_wr  ,

        i_fifo_empty        ,
        o_fifo_rd           ,
        iv_fifo_rdata       ,

        o_add_tag_flag      ,
        ov_ipv              ,
        ov_flowid           ,
        o_replication_flag  ,
        ov_seq_num          ,
        ov_inject_dbufid    , 
        
        ov_data             ,
        o_data_wr
    );
// I/O
// clk & rst
input                   i_clk;
input                   i_rst_n;
//input
input                   i_add_tag_flag;
input       [2:0]       iv_ipv;
input       [13:0]      iv_flowid;
input                   i_replication_flag;
input       [15:0]      iv_seq_num;
input       [4:0]       iv_inject_dbufid;
input                   i_lookup_finish_wr;

(*MARK_DEBUG="true"*)input                   i_fifo_empty;
(*MARK_DEBUG="true"*)output reg              o_fifo_rd;
(*MARK_DEBUG="true"*)input       [8:0]       iv_fifo_rdata;
//output 
output reg              o_add_tag_flag   ;
output reg  [2:0]       ov_ipv           ;
output reg  [13:0]      ov_flowid;
output reg              o_replication_flag;
output reg  [15:0]      ov_seq_num;
output reg  [4:0]       ov_inject_dbufid;
output reg  [8:0]       ov_data;
output reg              o_data_wr;

(*MARK_DEBUG="true"*)reg         [3:0]       rv_byte_cnt;
(*MARK_DEBUG="true"*)reg         [1:0]       rv_mfo_state;
localparam  IDLE_S                  = 2'd0,
            TRANS_FIRST_CYCLE_S     = 2'd1,
            TRANS_NOT_FIRST_CYCLE_S = 2'd2,
            DELAY_10CYCLES_S        = 2'd3;
always@(posedge i_clk or negedge i_rst_n)begin
    if(!i_rst_n) begin
        o_add_tag_flag       <= 1'b0;
        ov_ipv               <= 3'b0;
        ov_flowid            <= 14'b0;
        o_replication_flag   <= 1'b0;
        ov_seq_num           <= 16'b0;
        ov_inject_dbufid     <= 5'b0;
        
        o_fifo_rd            <= 1'b0;

        ov_data              <= 9'b0;
        o_data_wr            <= 1'b0;
        
        rv_byte_cnt          <= 4'b0;
                             
        rv_mfo_state         <= IDLE_S;
    end
    else begin
        case(rv_mfo_state)
            IDLE_S:begin 
                ov_data              <= 9'b0;
                o_data_wr            <= 1'b0; 
                rv_byte_cnt          <= 4'b0;                
                if(i_lookup_finish_wr)begin
                    o_add_tag_flag       <= i_add_tag_flag;
                    ov_ipv               <= iv_ipv;
                    ov_flowid            <= iv_flowid;
                    o_replication_flag   <= i_replication_flag;
                    ov_seq_num           <= iv_seq_num;
                    ov_inject_dbufid     <= iv_inject_dbufid;
                                     
                    o_fifo_rd            <= 1'b1;
                    rv_mfo_state         <= TRANS_FIRST_CYCLE_S;                    
                end
                else begin                    
                    o_add_tag_flag       <= 1'b0;
                    ov_ipv               <= 3'b0;
                    ov_flowid            <= 14'b0;
                    o_replication_flag   <= 1'b0;
                    ov_seq_num           <= 16'b0;
                    ov_inject_dbufid     <= 5'b0;
                    
                    o_fifo_rd              <= 1'b0;
                    rv_mfo_state           <= IDLE_S;
                end
            end
            TRANS_FIRST_CYCLE_S:begin
                ov_data             <= iv_fifo_rdata;
                o_data_wr           <= 1'b1;

                o_fifo_rd           <= 1'b1;                
                rv_mfo_state        <= TRANS_NOT_FIRST_CYCLE_S;                
            end
            TRANS_NOT_FIRST_CYCLE_S:begin
                ov_data             <= iv_fifo_rdata;
                o_data_wr           <= 1'b1; 
                if(iv_fifo_rdata[8])begin//last cycle of pkt
                    o_fifo_rd           <= 1'b0; 
                    if(o_add_tag_flag)begin
                        rv_mfo_state        <= DELAY_10CYCLES_S;   
                    end
                    else begin
                        rv_mfo_state        <= IDLE_S;
                    end                    
                end
                else begin
                    o_fifo_rd           <= 1'b1; 
                    rv_mfo_state        <= TRANS_NOT_FIRST_CYCLE_S;                
                end
            end
            DELAY_10CYCLES_S:begin//add 10B data(c-tag and r-tag)
                rv_byte_cnt          <= rv_byte_cnt + 1'b1; 
                ov_data              <= 9'b0;
                o_data_wr            <= 1'b0;                
                if(rv_byte_cnt == 4'd9)begin
                    rv_mfo_state        <= IDLE_S;  
                end
                else begin
                    rv_mfo_state        <= DELAY_10CYCLES_S;  
                end
            end            
            default:begin
                o_add_tag_flag       <= 1'b0;
                ov_ipv               <= 3'b0;
                ov_flowid            <= 14'b0;
                o_replication_flag   <= 1'b0;
                ov_seq_num           <= 16'b0;
                ov_inject_dbufid     <= 5'b0;
                    
                o_fifo_rd           <= 1'b0;
                ov_data             <= 9'b0;
                o_data_wr           <= 1'b0;
                
                rv_mfo_state        <= IDLE_S;
            end
        endcase
    end
end    
endmodule